package zdream.control.test.world;

import org.junit.Test;
import zdream.control.foe.mm2shot.MM2ShotMan;
import zdream.control.foe.mmcommon.Ashes;
import zdream.control.foe.mmcommon.AshesLeader;
import zdream.control.foe.mmcommon.HPCapsuleA;
import zdream.control.level.LevelManagerForTest;
import zdream.control.profile.mm.MegaManProfile;
import zdream.control.world.buff.HealthModule;
import zdream.control.world.MFoe;
import zdream.control.region.Region;
import zdream.control.region.SimpleRegionBuilder;
import zdream.control.world.LevelWorld;
import zdream.control.world.buff.SpoilsHolder;

import static org.junit.Assert.*;

/**
 * @author Zdream
 * @date 2023-12-25
 * @since 0.0.1
 */
public class LevelWorldCase {
	@Test
	public void testCreateLevelWorld() {
		Region region = new SimpleRegionBuilder(this.getClass().getSimpleName())
				.withRoomPositions("1")
				.withRoom(1)
						.terrain("#########################")
						.terrain("#########################")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("#########################")
						.terrain("#########################")
						.terrain("#########################")
						.build()
				.defineFoe("foe1", "MM2ShotMan")
				.withFoeSpawnAt(6, 3, "foe1")
				.build();
		System.out.println(region);
		assertEquals(1, region.rooms.length);

		LevelWorld world = new LevelWorld();
		world.setCurrentRoom(region.rooms[0]);

		assertEquals(1, world.foes.size());
		MFoe foe = world.foes.get(0);
		System.out.println(foe);

		assertTrue(foe.is(MM2ShotMan.NAME));
		assertTrue(foe.is(MM2ShotMan.TYPE_FOE));
		assertEquals(6, foe.anchorX, 0);
		assertEquals(3, foe.anchorY, 0);
		// -2/3f, 0, 1.375f, 1.375f
		assertEquals(1.375, foe.boxWidth, 0.01);
		assertEquals(1.375, foe.boxHeight, 0.01);
		assertEquals(6 - 2 / 3f, foe.pos.x, 0.01);
		assertEquals(3, foe.pos.y, 0.01);
		assertEquals(1.375, foe.pos.width, 0.01);
		assertEquals(1.375, foe.pos.height, 0.01);
		// patterns
		assertEquals(1, foe.patterns.size());
		assertEquals("normal", foe.patterns.get(0).name);

		world.render(1 / 60f);
	}

	@Test
	public void testCreateLevelManager() {
		Region region = new SimpleRegionBuilder(this.getClass().getSimpleName())
				.withRoomPositions("1")
				.withRoom(1)
						.terrain("#########################")
						.terrain("#########################")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##    A      S         ##")
						.terrain("#########################")
						.terrain("#########################")
						.terrain("#########################")
						.build()
				.defineFoe("foe1", "MM2ShotMan")
				.withFoeSpawnAt('A', "foe1")
				.withStartPoint('S')
				.build();
		System.out.println(region);
		assertEquals(1, region.rooms.length);

		MegaManProfile p1 = new MegaManProfile();

		LevelManagerForTest manager = LevelManagerForTest.builder()
				.withPlayer1(p1)
				.build();
		assertEquals(LevelWorld.STATE_NONE, manager.state);
		manager.applyWorld(region);
		manager.runOneFrame();
		assertEquals(LevelWorld.STATE_READY, manager.state);

		assertEquals(1, manager.findFoeByName(MM2ShotMan.NAME).size());
		MFoe mm2shotman = manager.findFoeByName(MM2ShotMan.NAME).get(0);
		assertEquals(6.5, mm2shotman.anchorX, 0.001);
		assertEquals(3, mm2shotman.anchorY, 0.001);
		assertTrue(mm2shotman.bottomTouched);

		manager.runUntil(ignored -> manager.player1 != null);
		assertEquals(LevelWorld.STATE_PLAYING, manager.state);
		System.out.printf("player1 已创建, worldTime = %.2f%n", manager.worldTime());

		assertTrue(manager.foes.size() >= 2);
		assertTrue(manager.player1.bottomTouched);

		// 设置 MM2ShotMan 死了之后的掉落物
		SpoilsHolder holder = new SpoilsHolder(mm2shotman);
		holder.addMass(HPCapsuleA.NAME, 1);
		mm2shotman.addBuff(holder);

		System.out.println("手动弄死 MM2ShotMan");
		HealthModule module = mm2shotman.findOneBuff(HealthModule.CATEGORY);
		module.hp = 0;
		manager.runOneFrame();
		assertTrue(mm2shotman.isDestroyed());

		assertEquals(1, manager.countFoeByName(Ashes.NAME));
		Ashes ashes = manager.findOneFoe(Ashes.NAME);
		assertEquals(mm2shotman.getCenterX(), ashes.anchorX, 0.001);
		assertEquals(mm2shotman.getCenterY(), ashes.anchorY, 0.001);

		manager.runUntil(ignored -> ashes.isDestroyed());
		HPCapsuleA capsule = manager.findOneFoe(HPCapsuleA.NAME);
		assertNotNull(capsule);
		assertEquals(mm2shotman.getCenterX(), capsule.anchorX, 0.001);
		assertEquals(mm2shotman.getCenterY(), capsule.anchorY, 0.001);

		System.out.println("手动弄死 megaman");
		assertEquals(LevelWorld.STATE_PLAYING, manager.state);
		module = manager.player1.findOneBuff(HealthModule.CATEGORY);
		module.hp = -100;
		manager.runOneFrame();
		assertTrue(manager.player1.isDestroyed());

		assertEquals(16, manager.countFoeByName(AshesLeader.NAME));
		assertEquals(LevelWorld.STATE_OVER, manager.state);
	}
}
